package accesstoken

import (
	"encoding/json"
	"errors"
	"ethereum/system/libraries/weixin/wxconfig"
	"ethereum/system/tools/helper"
	"ethereum/system/tools/mylog"
	"fmt"
	"io/ioutil"
	"net/http"
	"time"
)

type accessResponse struct {
	AccessToken string `json:"access_token"`
	ExpiresIn   int    `json:"expires_in"`
	ErrCode     int    `json:"errcode"`
	ErrMsg      string `json:"errmsg"`
}

type jsapiResponse struct {
	Ticket    string `json:"ticket"`
	ExpiresIn int    `json:"expires_in"`
	ErrCode   int    `json:"errcode"`
	ErrMsg    string `json:"errmsg"`
}

var (
	accessToken           string
	acceTokenCreateTime   time.Time
	jsapiTicket           string
	jsapiTicketCreateTime time.Time
)

func getAccessToken() (string, error) {
	var (
		err error
		ret = accessResponse{}
	)
	if accessToken == "" || acceTokenCreateTime.Add(time.Second*7000).Before(time.Now()) {
		_url := fmt.Sprintf("https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=%s&secret=%s",
			wxconfig.AppID, wxconfig.Secret)
		if req, e := http.NewRequest(http.MethodGet, _url, nil); e != nil {
			err = e
		} else if res, e := http.DefaultClient.Do(req); e != nil {
			err = e
		} else {
			defer res.Body.Close()

			if body, e := ioutil.ReadAll(res.Body); e != nil {
				err = e
			} else {
				if err = json.Unmarshal(body, &ret); err == nil {
					if ret.ErrCode != 0 {
						err = errors.New(ret.ErrMsg)
					} else if ret.AccessToken == "" {
						err = errors.New("access_token is empty")
					} else {
						accessToken = ret.AccessToken
						acceTokenCreateTime = time.Now()
					}
				}
			}
		}
	} else {
		ret.AccessToken = accessToken
	}
	return ret.AccessToken, err
}

func getJsapiTicket() (string, error) {
	var (
		err error
		ret = jsapiResponse{}
	)

	if jsapiTicket == "" || jsapiTicketCreateTime.Add(time.Second*7000).Before(time.Now()) {
		if asToken, e := getAccessToken(); e != nil {
			err = e
		} else {
			_url := fmt.Sprintf("https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token=%s&type=jsapi", asToken)
			if req, e := http.NewRequest(http.MethodGet, _url, nil); e != nil {
				err = e
			} else if res, e := http.DefaultClient.Do(req); e != nil {
				err = e
			} else {
				defer res.Body.Close()

				if body, e := ioutil.ReadAll(res.Body); e != nil {
					err = e
				} else {
					if err = json.Unmarshal(body, &ret); err == nil {
						if ret.ErrCode != 0 {
							err = errors.New(ret.ErrMsg)
						} else if ret.Ticket == "" {
							err = errors.New("access_token is empty")
						} else {
							jsapiTicket = ret.Ticket
							jsapiTicketCreateTime = time.Now()
						}
					}
				}
			}
		}
	} else {
		ret.Ticket = jsapiTicket
	}
	return ret.Ticket, err
}

// GetJsSdkSignature 获取 js-sdk 签名
func GetJsSdkSignature(data map[string]string) (string, error) {
	var (
		err error
		ret string
	)
	if jsTicket, e := getJsapiTicket(); e != nil {
		err = e
	} else {
		data["jsapi_ticket"] = jsTicket
		ret = helper.Sha1Encryption(helper.GetSignContent(data, ""))
	}
	if err != nil {
		mylog.LogOtherError("weixin", "GetJsSdkSignature:", err)
	}
	return ret, err
}
